package com.heima.wemedia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.api.IArticleClient;
import com.heima.common.constants.CacheConstants;
import com.heima.common.exception.CustomException;
import com.heima.model.admin.dots.ChannelDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.utils.common.UserThreadLocal;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.service.WmChannelService;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @Description TODO
 * @Author bo.li
 * @Date 2023/3/16 10:51
 * @Version 1.0
 */
@Service
@RequiredArgsConstructor
public class WmChannelServiceImpl extends ServiceImpl<WmChannelMapper, WmChannel> implements WmChannelService {

    private final WmChannelMapper channelMapper;

    private final IArticleClient articleClient;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private final static String CHANNEL = "CHANNEL";

    @Override
    public ResponseResult findAll() {
        return ResponseResult.okResult(list());
    }

    @Override
    @Cacheable(cacheNames = CacheConstants.CHANNEL_PREFIX, key = "#dto.getPage()+#dto.getName()")
    public PageResponseResult channelPage(ChannelDto dto) {
        Page<WmChannel> page = new Page(dto.getPage(), dto.getSize());

        LambdaQueryWrapper<WmChannel> wrapper = Wrappers.<WmChannel>lambdaQuery()
                .like(dto.getName() != null, WmChannel::getName, dto.getName());

        Page pageList = channelMapper.selectPage(page, wrapper);
        PageResponseResult responseResult = new PageResponseResult((int) pageList.getCurrent(),
                (int) pageList.getSize(), (int) pageList.getTotal());
        responseResult.setData(pageList.getRecords());
        return responseResult;
    }

    @Override
    @Caching(evict = {@CacheEvict(cacheNames = CacheConstants.CHANNEL_PREFIX, allEntries = true)})
    public ResponseResult saveChannel(WmChannel channel) {
        ValueOperations<String, String> operation = stringRedisTemplate.opsForValue();
//获取当前用户ID
        Integer userId = UserThreadLocal.get();
//幂等性
        if (!operation.setIfAbsent(CHANNEL + userId, "1", 1, TimeUnit.SECONDS)) {
            throw new CustomException(AppHttpCodeEnum.NOT_REPETITION_OPERATION);
        }
        channel.setCreatedTime(new Date());
        channel.setIsDefault(true);

        LambdaQueryWrapper<WmChannel> wrapper = Wrappers.<WmChannel>lambdaQuery()
                .eq(channel.getName() != null, WmChannel::getName, channel.getName());
        WmChannel wmChannel = channelMapper.selectOne(wrapper);

        if (wmChannel != null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "名字已重复，请重新命名！");
        }

        return ResponseResult.okResult(channelMapper.insert(channel));
    }

    @Override
    @Caching(evict = {@CacheEvict(cacheNames = CacheConstants.CHANNEL_PREFIX, allEntries = true)})
    public ResponseResult deleteById(Integer id) {
        WmChannel wmChannel = channelMapper.selectById(id);
        if (wmChannel.getStatus()) {
            return ResponseResult.errorResult(AppHttpCodeEnum.CHANNEL_CITED, "频道为开启状态，不能删除！");
        }

        return ResponseResult.okResult(channelMapper.deleteById(wmChannel.getId()));
    }

    @Override
    @Caching(evict = {@CacheEvict(cacheNames = CacheConstants.CHANNEL_PREFIX, allEntries = true)})
    public ResponseResult updateChannel(WmChannel channel) {
        if (StringUtils.isEmpty(channel.getDescription()) || !channel.getStatus()) {
            Integer channelSize = articleClient.channelSize(channel.getId());
            if (channelSize > 0) {
                return ResponseResult.errorResult(AppHttpCodeEnum.CHANNEL_CITED, "频道被引用不能禁用！");
            }
        }

        channel.setCreatedTime(new Date());

        return ResponseResult.okResult(channelMapper.updateById(channel));
    }
}